package rosedb.gui;

import com.explodingpixels.macwidgets.HudWidgetFactory;
import com.explodingpixels.macwidgets.HudWindow;
import java.awt.Color;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import java.awt.event.MouseWheelEvent;
import java.awt.geom.RoundRectangle2D;
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JViewport;


import rosedb.control.Controller;
import rosedb.model.Rose;

/**
 *
 * @author riu
 */
public class FeaturePanel extends JPanel{

    private Rose rose;
    

    private Color borderColor = Color.black;
    private Color keyColor = Color.decode("#ffff88");
    private Color valueColor = keyColor;

    private Color keyHighlightColor = Color.decode("#aaaaaa");
    private Color valueHighlightColor = Color.decode("#aaaaaa");



    private int topMargin = 20;
    private int spaceBetweenFeats = 10;
    private int featHeight;
    
    private boolean editMode = true;

    private ArrayList<JLabel> keyLabels = new ArrayList<JLabel>();
    private ArrayList<JLabel> valueLabels = new ArrayList<JLabel>();
    private ArrayList<JTextField> keyTextFields = new ArrayList<JTextField>();
    private ArrayList<JTextField> valueTextFields = new ArrayList<JTextField>();

    private String oldname = null;

    private Controller control;
    private MainFrame gui;
    private JScrollPane scroll;

    private int vertikalScrollPosition = 0;

    private FocusAdapter fl;
    private KeyListener kl;

    private int focused = -1;

    private String selectedFeature = null;
    private int hoveredFeature = -1;

    private MouseAdapter ma;

    public FeaturePanel(Controller c, MainFrame m, JScrollPane scr) {
        control = c;
        gui = m;
        scroll = scr;
        scroll.setWheelScrollingEnabled(true);
        setLayout(null);

        

        setOpaque(true); 

        addMouseListener(new MouseAdapter() {

            @Override
            public void mouseClicked(MouseEvent e) {
                selectedFeature = null;
                gui.getRemoveFeature().setEnabled(false);
                repaint();
            }
        });



        ma = new MouseAdapter() {

            @Override
            public void mouseWheelMoved(MouseWheelEvent e) { 
                if(keyLabels.size()>0){
                    Rectangle visible = getVisibleRect();
                    topMargin += e.getWheelRotation()<0 ? 20 : -20;

                    int max = visible.height-(featHeight+spaceBetweenFeats)*keyLabels.size()-featHeight;
                    int min = 20;


                    topMargin = topMargin<max ? max : topMargin;
                    topMargin = topMargin>min ? min : topMargin;

                    repaint();
                }
            }

            
            
            @Override
            public void mouseEntered(MouseEvent e) {
                int index = -1;

                if(e.getComponent() instanceof JTextField){
                    index  = hardIndexOf(e.getComponent(), keyTextFields);

                    if(index<0){
                        index = hardIndexOf(e.getComponent(), valueTextFields);
                    }

                    hoveredFeature = index;
                }

                else if(e.getComponent() instanceof JLabel){
                    index  = hardIndexOf(e.getComponent(), keyLabels);

                    if(index<0){
                        index = hardIndexOf(e.getComponent(), valueLabels);
                    }

                    hoveredFeature = index;
                }
            }

            @Override
            public void mouseExited(MouseEvent e) {
                hoveredFeature = -1;
            }

            @Override
            public void mouseClicked(MouseEvent e) {
                if(hoveredFeature>=0 && hoveredFeature < keyTextFields.size()){
                    selectedFeature = keyTextFields.get(hoveredFeature).getText();
                    gui.getRemoveFeature().setEnabled(true);
                }else{
                    selectedFeature = null;
                    gui.getRemoveFeature().setEnabled(false);
                }
                
                repaint();
            }

        };
        addMouseMotionListener(ma);
        addMouseWheelListener(ma);


        fl = new FocusAdapter() { 

            @Override
            public void focusGained(FocusEvent e) {
                e.getComponent().setBackground(Color.green);
            }

            @Override
            public void focusLost(FocusEvent e) {
                e.getComponent().setBackground(Color.white);
                focused = -1;
            }


        };

        kl = new KeyAdapter() {

            @Override
            public void keyTyped(KeyEvent e) {
                
            }

        };
    }

    private int hardIndexOf(Object o, List<? extends Object> list){
        for(int i=0; i<list.size(); i++){
            if(list.get(i) == o){
                return i;
            }
        }

        return -1;
    }

    public synchronized void loadRose(Rose r){
        topMargin = 20;
        if(r!=null && r!=rose){
            rose = r;
            removeAll();
            keyLabels.clear();
            valueLabels.clear();
            keyTextFields.clear();
            valueTextFields.clear();

            int i=0;
            for(Entry<String, String> e : rose.getData().entrySet()){
                keyLabels.add(HudWidgetFactory.createHudLabel(e.getKey()));
                valueLabels.add(HudWidgetFactory.createHudLabel(e.getValue()));
                keyTextFields.add(HudWidgetFactory.createHudTextField(e.getKey()));
                valueTextFields.add(HudWidgetFactory.createHudTextField(e.getValue()));

//                keyLabels.add(new JLabel(e.getKey()));
//                valueLabels.add(new JLabel(e.getValue()));
//                keyTextFields.add(new JTextField(e.getKey()));
//                valueTextFields.add(new JTextField(e.getValue()));
                
                keyTextFields.get(i).setEditable(false);

                add(keyLabels.get(i));
                add(valueLabels.get(i));
                add(keyTextFields.get(i));
                add(valueTextFields.get(i));

                valueTextFields.get(i).addFocusListener(fl);


                keyLabels.get(i).addMouseListener(ma);
                valueLabels.get(i).addMouseListener(ma);
                keyTextFields.get(i).addMouseListener(ma);
                valueTextFields.get(i).addMouseListener(ma);

                keyLabels.get(i).setForeground(keyColor);
                valueLabels.get(i).setForeground(valueColor);
                

//                g.drawString("Name", (getWidth()*3/4)/8, topMargin + (g.getFont().getSize()*3+spaceBetweenFeats)*2*i + g.getFont().getSize()*2);
//                g.drawString(rose.getName(), (getWidth()*3/4)/8+getWidth()/4, topMargin + (g.getFont().getSize()*3 + spaceBetweenFeats)*(2*i+1) + g.getFont().getSize()*2 - spaceBetweenFeats);


                keyLabels.get(i).setBounds((scroll.getWidth()*3/4)/8, topMargin + (getFont().getSize()*3+spaceBetweenFeats)*2*i + getFont().getSize()/2, (scroll.getWidth()*3/4)/8*6, getFont().getSize()*2);
                keyTextFields.get(i).setBounds((scroll.getWidth()*3/4)/8, topMargin + (getFont().getSize()*3+spaceBetweenFeats)*2*i + getFont().getSize()/2, (scroll.getWidth()*3/4)/8*6, getFont().getSize()*2);

                valueLabels.get(i).setBounds((scroll.getWidth()*3/4)/8+scroll.getWidth()/4, topMargin + (getFont().getSize()*3 + spaceBetweenFeats)*(2*i+1) + getFont().getSize()/2 - spaceBetweenFeats, (scroll.getWidth()*3/4)/8*6, getFont().getSize()*2);
                valueTextFields.get(i).setBounds((scroll.getWidth()*3/4)/8+scroll.getWidth()/4, topMargin + (getFont().getSize()*3 + spaceBetweenFeats)*(2*i+1) + getFont().getSize()/2 - spaceBetweenFeats, (scroll.getWidth()*3/4)/8*6, getFont().getSize()*2);

//                (keyLabels.get(i)).repaint();
//                (valueLabels.get(i)).repaint();
//                (keyTextFields.get(i)).repaint();
//                (valueTextFields.get(i)).repaint();
                
                i++;
            }

            for(int j=1; j<keyLabels.size(); j++){
                if(keyLabels.get(j).getText().equalsIgnoreCase("name")){
                    keyLabels.set(j, keyLabels.set(0, keyLabels.get(j)));
                    valueLabels.set(j, valueLabels.set(0, valueLabels.get(j)));
                    keyTextFields.set(j, keyTextFields.set(0, keyTextFields.get(j)));
                    valueTextFields.set(j, valueTextFields.set(0, valueTextFields.get(j)));
                }
            }

            editMode(false);

        }


        rose = r;
        repaint();
        
    }

    public boolean isInEditMode(){
        return editMode;
    }

    public void editMode(boolean edit){
        if(rose==null){
            editMode = false;
            gui.getEditFeatures().setText("bearbeiten");
            return;
        }

        if(!edit){
            for(int i=0; i<valueTextFields.size(); i++){
                
                if(!keyTextFields.get(i).getText().equalsIgnoreCase("name")){
                    valueLabels.get(i).setText(valueTextFields.get(i).getText());
                    rose.getData().put(keyTextFields.get(i).getText(), valueTextFields.get(i).getText());
                }else{
                    if(!valueTextFields.get(i).getText().equals(rose.getData().get("name"))){
                        if(control.renameRose(valueTextFields.get(i).getText())){
                            valueLabels.get(i).setText(valueTextFields.get(i).getText());
                            
                        }
                    }
                }
            }

            control.updateRose();
        }

        
        editMode = edit;
        if(editMode){
            oldname = rose.getName();
        }

        for(JTextField t : keyTextFields){
            t.setVisible(editMode);
        }
        for(JTextField t : valueTextFields){
            t.setVisible(editMode);
        }
        for(JLabel t : keyLabels){
            t.setVisible(!editMode);
        }
        for(JLabel t : valueLabels){
            t.setVisible(!editMode);
        }

        gui.getEditFeatures().setText(editMode ? "fertig" : "bearbeiten");

        repaint();
               
    }

    public void addFeature(){
        List<String> hide = new ArrayList<String>();
        for(String s : rose.getData().keySet()){
            hide.add(s);
        }

        //FeatureDialog d = new FeatureDialog(gui, true, control.getData(), control, hide);
        final HudWindow featureDialog = new HudWindow("Eigenschaft hinzufügen", gui);
        UsedFeaturesPanel d = new UsedFeaturesPanel(control.getData(), control, hide);
        featureDialog.setContentPane(d);
        
        featureDialog.getJDialog().setSize(250, 300);
        

        featureDialog.getJDialog().setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
        Container c = gui;
        Dimension dd = c.getSize();
        featureDialog.getJDialog().setLocation(dd.width/2-featureDialog.getJDialog().getWidth()/2+c.getX(), dd.height/2-featureDialog.getJDialog().getHeight()/2+c.getY());
        featureDialog.getJDialog().setModal(true);
        featureDialog.getJDialog().setVisible(true);

        if(d.getPickedFeature()!=null){
            rose.getData().put(d.getPickedFeature(), "");
            Rose r = rose;
            rose = null;
            loadRose(r);
            editMode(true);
            int i=0;
            for(JTextField jt : keyTextFields){
                if(jt.getText().equalsIgnoreCase(d.getPickedFeature())){
                    valueTextFields.get(i).requestFocusInWindow();
                }

                i++;
            }

            selectedFeature = d.getPickedFeature();
            gui.getRemoveFeature().setEnabled(true);
        }

        featureDialog.getJDialog().dispose();

        repaint();
    }

    public void removeFeature(){
        String featureName = selectedFeature;

        if(featureName!=null && !featureName.equalsIgnoreCase("name")){
            int i, found=-1;
            for(i=0; i<keyTextFields.size(); i++){
                if(keyTextFields.get(i).getText().equalsIgnoreCase(featureName)){
                    found = i;
                }
            }

            if(found!=-1){
                remove(keyTextFields.remove(found));
                remove(valueTextFields.remove(found));
                remove(keyLabels.remove(found));
                remove(valueLabels.remove(found));
            }

            selectedFeature = null;
            gui.getRemoveFeature().setEnabled(false);
            rose.getData().remove(featureName);
            control.updateRose();
            repaint(); 
            loadRose(rose);
            
        }
    }

    public void setController(Controller c){
        control = c;
    }

    @Override
    public void paint(Graphics g) {
        
        featHeight = 0;
        g.setColor(getBackground());
        g.clearRect(0, 0, getWidth(), getHeight());
        g.fillRect(0, 0, getWidth(), getHeight());

        keyHighlightColor = getBackground().brighter();
        valueHighlightColor = getBackground().brighter();

        g.setColor(getBackground().darker());
        g.fillRoundRect(getVisibleRect().x, getVisibleRect().y, getVisibleRect().width, getVisibleRect().height, 20, 20);
        RoundRectangle2D rec = new RoundRectangle2D.Float(getVisibleRect().x, getVisibleRect().y, getVisibleRect().width, getVisibleRect().height, 20, 20);
        ((Graphics2D)g).clip(rec);

        if(rose!=null){
            
            int i=0;

            for(int j=0; j<keyTextFields.size(); j++){
                
                keyLabels.get(j).setBounds((scroll.getWidth()*3/4)/8, topMargin + (getFont().getSize()*3+spaceBetweenFeats)*2*i + getFont().getSize()/2, (scroll.getWidth()*3/4)/8*6, getFont().getSize()*2);
                keyTextFields.get(j).setBounds((scroll.getWidth()*3/4)/8, topMargin + (getFont().getSize()*3+spaceBetweenFeats)*2*i + getFont().getSize()/2, (scroll.getWidth()*3/4)/8*6, getFont().getSize()*2);

                valueLabels.get(j).setBounds((scroll.getWidth()*3/4)/8+scroll.getWidth()/4, topMargin + (getFont().getSize()*3 + spaceBetweenFeats)*(2*i+1) + getFont().getSize()/2 - spaceBetweenFeats, (scroll.getWidth()*3/4)/8*6, getFont().getSize()*2);
                valueTextFields.get(j).setBounds((scroll.getWidth()*3/4)/8+scroll.getWidth()/4, topMargin + (getFont().getSize()*3 + spaceBetweenFeats)*(2*i+1) + getFont().getSize()/2 - spaceBetweenFeats, (scroll.getWidth()*3/4)/8*6, getFont().getSize()*2);
                
                keyLabels.get(j).setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
                valueLabels.get(j).setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));


                if(keyTextFields.get(i).getText().equalsIgnoreCase(selectedFeature)){
                    g.setColor(keyHighlightColor);
                    g.fillRoundRect(0, topMargin + (getFont().getSize()*3+spaceBetweenFeats)*2*i, scroll.getWidth()*3/4, getFont().getSize()*3, 50, 50);
                    g.setColor(valueHighlightColor);
                    g.fillRoundRect(scroll.getWidth()/4, topMargin + (getFont().getSize()*3 + spaceBetweenFeats)*(2*i+1) - spaceBetweenFeats, scroll.getWidth()*3/4, getFont().getSize()*3, 50, 50);
                }

                g.setColor(borderColor);
                g.drawRoundRect(0, topMargin + (getFont().getSize()*3+spaceBetweenFeats)*2*i, scroll.getWidth()*3/4, getFont().getSize()*3, 50, 50);
                g.drawRoundRect(scroll.getWidth()/4, topMargin + (getFont().getSize()*3 + spaceBetweenFeats)*(2*i+1) - spaceBetweenFeats, scroll.getWidth()*3/4, getFont().getSize()*3, 50, 50);
                featHeight = getFont().getSize()*3 * 2;


                

                
                i++;
            }

            paintComponents(g);
        }
        
        
    }



   



}
